﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Entidades;
using Controladores;
using Common;
using System.Text;

namespace Web.Helpers
{
    public class FacturacionHelper
    {
        public class InfoCalculoPago
        {
            public int CantidadCanciones{ get; set; }
            public int CantidadCoros { get; set; }
            public int CantidadPalabras { get; set; }
            public int CantidadLoops { get; set; }
            public decimal ImporteCanciones { get; set; }
            public decimal ImporteLoops { get; set; }
            public decimal ImporteTotal { get; set; }
            public int IdGuion { get; set; }
            public int IdUsuario { get; set; }
            public int IdTipoUsuario { get; set; }
            public DateTime Fecha { get; set; }
        }

        public static decimal ObtenerValorPorTipoUsuario(GuionCosto costo, int idTipoUsuario)
        {
            decimal valorCosto = 0;
            switch (idTipoUsuario)
            {
                case WellKnownKeys.Entities.TiposUsuario.ACTOR.Id:
                    //valorCosto = costo.Actor;
                    break;
                case WellKnownKeys.Entities.TiposUsuario.ADAPTADOR.Id:
                    valorCosto = costo.Adaptacion;
                    break;
                case WellKnownKeys.Entities.TiposUsuario.ADMINISTRADOR.Id:
                case WellKnownKeys.Entities.TiposUsuario.PRODUCCION.Id:
                    //valorCosto = costo.Administrador;
                    break;
                case WellKnownKeys.Entities.TiposUsuario.DIRECTOR.Id:
                    valorCosto = costo.Direccion;
                    break;
                case WellKnownKeys.Entities.TiposUsuario.EDITOR.Id:
                    //valorCosto = costo.Editor;
                    break;
                case WellKnownKeys.Entities.TiposUsuario.MEZCLADOR.Id:
                    valorCosto = costo.Mezcla;
                    break;
                case WellKnownKeys.Entities.TiposUsuario.OPERADOR.Id:
                    //valorCosto = costo.Operador;
                    break;
                case WellKnownKeys.Entities.TiposUsuario.TRADUCTOR.Id:
                    valorCosto = costo.Traduccion;
                    break;
            }
            return valorCosto;
        }
        //public static DateTime CalcularFechaDePago(DateTime fecha)
        //{
        //    //Obtener el 1° del mes siguiente, y sumarle 45 días..
        //    return new DateTime(fecha.Year, fecha.Month, 1).AddMonths(1).AddDays(44); //sumo 44 al día 1 (sino, quedaría en el 16vo día, y no el 15vo..)
        //}
        public static object ObtenerFechaPago(int idEstadoPago, DateTime fecha, DateTime? fechaPago)
        {
            object _fecha = null;
            switch (idEstadoPago)
            {
                case WellKnownKeys.Entities.EstadosPago.PENDIENTE_DE_PAGO.Id:
                    //_fecha = FacturacionHelper.CalcularFechaDePago(fecha);
                    _fecha = fecha;
                    break;
                case WellKnownKeys.Entities.EstadosPago.PAGADO.Id:
                    _fecha = fechaPago.HasValue ? fechaPago.Value : new DateTime?();
                    break;
            }
            return _fecha;
        }

        public static InfoCalculoPago CalcularPagoNoActores(Guion guion, int idUsuario, int idTipoUsuario, int idCategoriaUsuario)
        {
            var importe = 0m;

            var generarPago = true;

            var infoCalculoPago = default(InfoCalculoPago);

            if (idCategoriaUsuario == WellKnownKeys.Entities.CategoriasUsuario.FREELANCE.Id)
            {
                switch (guion.Proyecto.Tipo.Id)
                {
                    case WellKnownKeys.Entities.TiposProyecto.SERIE.Id:
                        importe = FacturacionHelper.ObtenerValorPorTipoUsuario(guion.Costo, idTipoUsuario) * guion.Loops;
                        break;
                    case WellKnownKeys.Entities.TiposProyecto.VIDEOJUEGO.Id:
                        switch (idTipoUsuario)
                        {
                            case WellKnownKeys.Entities.TiposUsuario.ADAPTADOR.Id:
                            //case WellKnownKeys.Entities.TiposUsuario.ADMINISTRADOR.Id:
                            case WellKnownKeys.Entities.TiposUsuario.DIRECTOR.Id:
                            case WellKnownKeys.Entities.TiposUsuario.EDITOR.Id:
                            case WellKnownKeys.Entities.TiposUsuario.MEZCLADOR.Id:
                            case WellKnownKeys.Entities.TiposUsuario.OPERADOR.Id:
                                generarPago = false;
                                break;
                            case WellKnownKeys.Entities.TiposUsuario.TRADUCTOR.Id:
                                importe = guion.Costo.Traduccion * guion.Loops;
                                break;
                        }
                        break;
                }

            }

            if (idCategoriaUsuario == WellKnownKeys.Entities.CategoriasUsuario.CONTRATADO.Id)
            {
                importe = 0;
            }

            if (generarPago)
            {
                infoCalculoPago = new InfoCalculoPago
                {
                    Fecha               = guion.FechaCreacion,
                    IdGuion             = guion.Id,
                    IdUsuario           = idUsuario,
                    IdTipoUsuario       = idTipoUsuario,
                    CantidadLoops       = guion.Loops,
                    CantidadCanciones   = 0,
                    CantidadCoros       = 0,
                    CantidadPalabras    = 0,
                    ImporteCanciones    = 0,
                    ImporteLoops        = importe,
                    ImporteTotal        = importe
                };
            }

            return infoCalculoPago;
        }
        public static InfoCalculoPago CalcularPagoActores(ProyectoTipo tipoProyecto, GuionCosto costo, List<GuionItem> guionItemsDelActor)
        {
            var guion = guionItemsDelActor.First();

            if (guion.IsNull())
                return null;

            var infoCalculoPago = new InfoCalculoPago
            {
                Fecha               = guion.FechaGrabacion.HasValue ? guion.FechaGrabacion.Value : guion.Guion.FechaCreacion,
                IdGuion             = guion.Guion.Id,
                IdUsuario           = guion.Actor.Id,
                IdTipoUsuario       = guion.Actor.Tipo.Id,
                CantidadCanciones   = guionItemsDelActor.Count(x => x.TipoCancion.IsNotNull() && x.TipoCancion.Id == WellKnownKeys.Entities.TiposCancion.CANCION.Id),
                CantidadCoros       = guionItemsDelActor.Count(x => x.TipoCancion.IsNotNull() && x.TipoCancion.Id == WellKnownKeys.Entities.TiposCancion.CORO.Id),
                CantidadPalabras    = guionItemsDelActor.Count(x => x.TipoCancion.IsNotNull() && x.TipoCancion.Id == WellKnownKeys.Entities.TiposCancion.PALABRAS.Id),
                CantidadLoops       = guionItemsDelActor.Sum(x => x.Loops)
            };

            const int cantidadMinimaLoops = 10;

            if (guion.Actor.Categoria.Id == WellKnownKeys.Entities.CategoriasUsuario.FREELANCE.Id)
            {
                switch (tipoProyecto.Id)
                {
                    case WellKnownKeys.Entities.TiposProyecto.SERIE.Id:
                        infoCalculoPago.ImporteLoops = infoCalculoPago.CantidadLoops <= cantidadMinimaLoops ? costo.LoopMinimo : costo.LoopMinimo + (costo.Loops * (infoCalculoPago.CantidadLoops - cantidadMinimaLoops ) );
                        break;
                    case WellKnownKeys.Entities.TiposProyecto.VIDEOJUEGO.Id:
                        infoCalculoPago.ImporteLoops = costo.LoopMinimo + (costo.Loops * infoCalculoPago.CantidadLoops);
                        break;
                }

                infoCalculoPago.ImporteCanciones = ((costo.Cancion*infoCalculoPago.CantidadCanciones) +
                                                    (costo.Coro*infoCalculoPago.CantidadCoros) +
                                                    (costo.Palabras*infoCalculoPago.CantidadPalabras));

                infoCalculoPago.ImporteTotal = infoCalculoPago.ImporteCanciones + infoCalculoPago.ImporteLoops;                
            }

            if (guion.Actor.Categoria.Id == WellKnownKeys.Entities.CategoriasUsuario.CONTRATADO.Id)
            {
                infoCalculoPago.ImporteLoops = 0;
                infoCalculoPago.ImporteCanciones = 0;
                infoCalculoPago.ImporteTotal = 0;
            }

            return infoCalculoPago;
        }
        public static InfoCalculoPago CalcularPagoTemporizador(Guion guion, int idUsuario, int idTipoUsuario, int idCategoriaUsuario)
        {
            var importe = 0m;

            var infoCalculoPago = default(InfoCalculoPago);

            var costoTemporizacion = guion.Costo.Temporizacion;

            var cantidadLoopsSubtitulados = 0;

            var personajesSubtitulados = guion.Items.Where(x => x.Subtitulado);
            if (personajesSubtitulados.Any())
                cantidadLoopsSubtitulados = personajesSubtitulados.Sum(x => x.Loops);

            if (idCategoriaUsuario == WellKnownKeys.Entities.CategoriasUsuario.FREELANCE.Id)
            {
                switch (guion.Proyecto.Tipo.Id)
                {
                    case WellKnownKeys.Entities.TiposProyecto.SERIE.Id:
                        importe = costoTemporizacion * cantidadLoopsSubtitulados;
                        break;
                    case WellKnownKeys.Entities.TiposProyecto.VIDEOJUEGO.Id:
                        break;
                }
            }
            if (idCategoriaUsuario == WellKnownKeys.Entities.CategoriasUsuario.CONTRATADO.Id)
            {
                importe = 0;
            }

            infoCalculoPago = new InfoCalculoPago
            {
                Fecha               = guion.FechaCreacion,
                IdGuion             = guion.Id,
                IdUsuario           = idUsuario,
                IdTipoUsuario       = idTipoUsuario,
                CantidadLoops       = cantidadLoopsSubtitulados,
                CantidadCanciones   = 0,
                CantidadCoros       = 0,
                CantidadPalabras    = 0,
                ImporteCanciones    = 0,
                ImporteLoops        = importe,
                ImporteTotal        = importe
            };
            
            return infoCalculoPago;
        }
        public static Pago GenerarPago(ControladorBase<Pago> controladorBase, InfoCalculoPago infoCalculoPago, PagoEstado estadoPago, DateTime? fechaPago = null, PagoMedio medioPago = null)
        {
            var pago = default(Pago);
            try
            {
                pago = new PagoControlador().ObtenerPago(infoCalculoPago.IdUsuario, infoCalculoPago.IdTipoUsuario, infoCalculoPago.IdGuion, estadoPago.Id);
                pago = pago.IsNotNull()
                    ? controladorBase.ObtenerEntidad(pago.Id)
                    : new Pago() { Guion = new ControladorBase<Guion>().ObtenerEntidad(infoCalculoPago.IdGuion) };

                //pago.Id               = -1;
                pago.Activo             = true;
                pago.Fecha              = infoCalculoPago.Fecha;
                pago.Loops              = infoCalculoPago.CantidadLoops;
                pago.ImporteLoops       = infoCalculoPago.ImporteLoops;
                pago.Canciones          = infoCalculoPago.CantidadCanciones + infoCalculoPago.CantidadCoros + infoCalculoPago.CantidadPalabras;
                pago.ImporteCanciones   = infoCalculoPago.ImporteCanciones;
                pago.ImporteTotal       = infoCalculoPago.ImporteTotal;
                pago.Proveedor          = new ControladorBase<Usuario>().ObtenerEntidad( infoCalculoPago.IdUsuario );
                pago.ProveedorRol       = new ControladorBase<UsuarioTipo>().ObtenerEntidad(x => x.Id == infoCalculoPago.IdTipoUsuario);
                pago.Estado             = pago.Estado ?? estadoPago;
                pago.FechaPago          = pago.FechaPago.HasValue ? pago.FechaPago.Value : fechaPago; 
                pago.MedioPago          = pago.MedioPago ?? medioPago;
            }
            catch (Exception)
            {                
                throw;
            }
            return pago;
        }
    }
}